package irisweb

import (
	"fmt"
	"reflect"
	"runtime"
	"strconv"

	"github.com/kataras/iris"
)

// WriteJSON 将返回对象以正确格式写入到返回流
func WriteJSON(ctx iris.Context, data interface{}) {
	ctx.JSON(iris.Map{
		"code": 0,
		"data": data,
	})
}

// WriteJSONError 将错误以JSON格式写入到返回
func WriteJSONError(ctx iris.Context, statusCode int, eCode int, eName, eMessage string) {
	err := iris.Map{
		"code":    eCode,
		"name":    eName,
		"message": eMessage,
	}

	// 写日志
	ctx.Application().Logger().Warn(GetErrorCallstackLogs(ctx, err))

	ctx.JSON(iris.Map{
		"code": statusCode,
		"data": err,
	})
}

// GetRequestLogs 获取请求日志
func GetRequestLogs(ctx iris.Context) string {
	var status, ip, method, path string
	status = strconv.Itoa(ctx.GetStatusCode())
	path = ctx.Path()
	method = ctx.Method()
	ip = ctx.RemoteAddr()
	// the date should be logged by iris' Logger, so we skip them
	return fmt.Sprintf("%v %s %s %s", status, path, method, ip)
}

// GetErrorCallstackLogs 获取错误时的调用堆栈
func GetErrorCallstackLogs(ctx iris.Context, err interface{}) string {
	var stacktrace string
	for i := 1; ; i++ {
		_, f, l, got := runtime.Caller(i)
		if !got {
			break

		}

		stacktrace += fmt.Sprintf("%s:%d\n", f, l)
	}

	logMessage := fmt.Sprintf("Recovered from a route's Handler('%s')\n", ctx.HandlerName())
	logMessage += fmt.Sprintf("At Request: %s\n", GetRequestLogs(ctx))
	logMessage += fmt.Sprintf("Trace: %s\n", err)
	logMessage += fmt.Sprintf("\n%s", stacktrace)

	return logMessage
}

// ReadJSON 转换为对象
func ReadJSON(ctx iris.Context, jsonObject interface{}) error {
	if err := ctx.ReadJSON(jsonObject); err != nil {
		panic(fmt.Sprintf("invalid request body: %s", reflect.TypeOf(jsonObject)))
	}

	return nil
}
